const isCallable = (fn: () => void) => typeof fn === 'function'
const noop = () => {}

export const jsApiList: WechatJssdk.JsApiNames[] = [
  'checkJsApi',

  /* 分享接口 */
  'updateAppMessageShareData',
  'updateTimelineShareData',
  'onMenuShareTimeline',
  'onMenuShareAppMessage',
  'onMenuShareQQ',
  'onMenuShareWeibo',
  'onMenuShareQZone',

  /* 图像接口 */
  'chooseImage',
  'previewImage',
  'uploadImage',
  'downloadImage',
  'getLocalImgData',

  /* 音频接口 */
  'startRecord',
  'stopRecord',
  'playVoice',
  'pauseVoice',
  'stopVoice',
  'uploadVoice',
  'downloadVoice',

  /* 智能接口 */
  'translateVoice',

  /* 设备信息 */
  'getNetworkType',

  /* 地理位置 */
  'openLocation',
  'getLocation',

  /* 摇一摇周边 */
  'startSearchBeacons',
  'stopSearchBeacons',

  /* 界面操作 */
  'hideMenuItems',
  'showMenuItems',
  'hideAllNonBaseMenuItem',
  'showAllNonBaseMenuItem',

  /* 微信扫一扫 */
  'scanQRCode',

  /* 微信小店 */
  'openProductSpecificView',

  /* 微信卡券 */
  'chooseCard',
  'addCard',
  'openCard',
  'consumeAndShareCard',

  /* 微信支付 */
  'chooseWXPay',
  'openBusinessView',

  /* 快速输入 */
  'openAddress',

  /* 小程序 */
  'launchMiniProgram',

  /* 企业微信 */
  'openEnterpriseRedPacket',
  'openEnterpriseChat',
]

export const initWechatPromisyFuncs = () => {
  jsApiList.forEach(prop => {
    let fn: any = wx[prop]
    if (!isCallable(fn)) {
      fn = (args: any) => {
        if (typeof args === 'object') {
          if (isCallable(args.fail))
            args.fail({ errMsg: `${prop}:not supported` })

          if (isCallable(args.complete))
            args.complete({ errMsg: `${prop}:not supported` })
        }
      }
    }

    const newFn = (args: any) => {
      args = {
        success: noop,
        fail: noop,
        complete: noop,
        ...args,
      }

      const successFn = args.success
      const failFn = args.fail
      const completeFn = args.complete

      const p = new Promise((resolve, reject) => {
        args.success = (res: any) => resolve(res)
        args.fail = (res: any) => reject(res)
        args.complete = noop

        fn(args)
      })
        .then(res => {
          if (isCallable(successFn)) successFn(res)

          return Promise.resolve(res)
        })
        .catch(res => {
          if (isCallable(failFn)) failFn(res)

          return Promise.reject(res)
        })

      if (isCallable(p.finally)) {
        p.finally(() => {
          if (isCallable(completeFn)) completeFn()
        })
      }

      return p
    }

    ;(wx as any)[`${prop}Async`] = newFn
  })

  wx.invokeSync = apiName => {
    return new Promise((resolve, reject) => {
      wx.invoke(apiName, res => {
        res?.err_msg?.includes('ok') ? resolve(res) : reject(res)
      })
    })
  }
}

// 注册企业微信sdk
const initWorkWechat = ({
  corpid,
  agentid,
  timestamp,
  nonceStr,
  signature,
}: WechatJssdk.AgentConfigOption) => {
  console.log('------- agentConfig start -------')
  return new Promise<{ errMsg: string }>((resolve, reject) => {
    wx.agentConfig({
      corpid,
      agentid,
      timestamp,
      nonceStr,
      signature,
      jsApiList: [
        'selectExternalContact',
        'openUserProfile',
        'shareToExternalContact',
        'sendChatMessage',
        'getCurExternalContact',
        'getCurExternalChat',
        'applyCodeForCreateChat',
        'openDefaultBrowser',
        'selectCorpGroupContact',
        'createCorpGroupChat',
        'updateCorpGroupChat',
        'openExistedChatWithMsg',
      ],
      success(res) {
        // 回调
        console.log('------- agentConfig success -------', res)
        resolve(res)
      },
      fail(res) {
        console.log('------- agentConfig fail -------', res)
        if (res.errMsg.includes('function not exist')) alert('版本过低请升级')

        reject(res)
      },
    })
  })
}

export const initWechat = async () => {
  const { isWechatEnv, isWechatWorkEnv } = useSystemStore()
  if (!isWechatEnv) return
  const userStore = useUserStore()

  try {
    const [error, data] = await callApi({
      api: 'wechat_oauth2_getJsApiSignature',
      params: {
        appid: userStore.appid,
        historyUrl: location.href.split('#')[0],
      },
    })
    if (error) return Toast.fail('微信SDK注册失败')

    wx?.config({
      // debug: import.meta.env.DEV, // 开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，参数信息会通过log打出，仅在pc端时才会打印。
      ...data,
      appId: data.wxappid,
      jsApiList, // 必填，需要使用的JS接口列表
    })
    const isUseOpenData = !!data.isUseOpenData

    if (isWechatWorkEnv && isUseOpenData) await initWorkWechat(data)

    userStore.setUserInfo({ isUseOpenData })
  } catch (error) {
    console.log('微信 js-sdk 注册失败', error)
  }
}
